#ifndef MCMC_REGION_MODEL_H
#define MCMC_REGION_MODEL_H

#include "mcRasterColor.h"
#include "mcmcParticle.h"
#include "mcmcParticleSurface.h"


class MCMC_AtomicRegion;
class MCMC_Layer_Regions;
class MCMC_Layer_SnakeCurves;

extern double scale_factor;

#define MAX_ROBUST_DIST			35.0
#define MAX_ROBUST_DIST2		35.0*35.0

#define	MINIMAL_SIZE			11.0		// minimal size of regions that are allowed to appear
#define PENALTY_REGIONS_FEW_PIXELS	500.0

#define CV_LOW					1.0
#define CV_HIGH					3.0

// model types
#define MODEL_LUVCOLOR_GAUSS			1
#define MODEL_LUVCOLOR_MIXTUREGAUSS		2

#define MODEL_2DCOLOR_GAUSS				3
#define MODEL_3DCOLOR_GAUSS				4
#define MODEL_3DCOLOR_MIXGAUSS			5

#define	MODEL_TEXTURE					6		// independent gaussians in intensity and color

#define	MODEL_INTENSITY_GAUSS			7
#define MODEL_INTENSITY_MIXGAUSS		8
#define MODEL_INTENSITY_TEXTURE			9
#define MODEL_INTENSITY_DELTA			10
#define MODEL_INTENSITY_SURFACE			11

#define MODEL_LUVCOLOR_SURFACE			12
#define MODEL_INTENSITY_FACE			13
#define MODEL_INTENSITY_TEXT            14

#define NUM_MODEL_TYPE					14

#define COMPLEXITY_POW			0.9

////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// top level class for a region
class MCMC_Model
{
public:
	// constructions & destructions
	MCMC_Model();
	virtual ~MCMC_Model();

	// operators
	MCMC_Model& operator=(const MCMC_Model&x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual void		SetImage(MCMC_FilterResp &respFilter){prespFilter=&respFilter;};
	virtual void		SetMatrixLabel(mcmcMatrix<int> &mx_label)=0;
	virtual void		SetBound(const irmm_Rect bound1)=0;
	virtual void		SetMatrixTaken(mcmcMatrix<int> &mx_taken)=0;
	virtual void		SetParticel(MCMC_Particle &particle){;};
	inline int			Type(void){return type;};

	virtual bool		Mean(const int nlabel)=0;
	virtual	void		DiffuseComputedMean(const int nlabel)=0;
	// robust statistics
	virtual bool		Variance(const int nlabel)=0;
	virtual bool		LogLikelihood(const int nlable)=0;
	virtual void		UpdateLogLikelihood(const int nlabel, MCMC_PixelSet &list_pixels_old, MCMC_PixelSet &list_pixels_new){;};

	virtual void		GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel)=0;
	virtual double		GetDirectDis(mcmcVector<double> &vc_pixel_value)=0;
	virtual double		GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL)=0;

	virtual double		GetPdf(void)=0;
	virtual MCMC_Model* CopyTo(void)=0;

	virtual void		PrepreForSynthesize(void)=0;
	virtual bool		SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col)=0;
	virtual bool		Reconstruct(mcmcVector<double> &vc_a, const int row, const int col)=0;
	inline	double		Complexity(void){return complexity_prior;};
	virtual void		OutputInfo(char *info){};

	virtual mcmcVector<float> ComputeVote(const int nlable)=0;
	virtual mcmcVector<double> GetAMean(void)=0;
	virtual int		TotalCodingBits(void)=0;
	inline  double		EnergyImageModel(void){return log_pos_prob;};

public:
	mcmcVector<float>	vc_vote;
	double			crying_voice;
	int			nsize;
	double			log_lik;	// log of probability without penality for region size

protected:
	double				log_pos_prob;
	MCMC_FilterResp		*prespFilter;
	int					type;
	double				complexity_prior;
};

MCMC_Model *CreateModel(const int type);
bool CopyModel(MCMC_Model *pmodel1, MCMC_Model *pmodel2);


class MCMC_RegionModel : public MCMC_Model
{
public:
	// constructions & destructions
	MCMC_RegionModel();
	virtual ~MCMC_RegionModel();
	virtual void Free(void);

	// operators
	MCMC_RegionModel& operator=(const MCMC_RegionModel &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual void			SetParticel(MCMC_Particle &particle){pparticle=&particle;};
	virtual void			SetMatrixLabel(mcmcMatrix<int> &mx_label){pmx_label=&mx_label;};
	virtual void			SetMatrixTaken(mcmcMatrix<int> &mx_taken){pmx_taken=&mx_taken;};
	virtual void			SetBound(const irmm_Rect bound1){bound=bound1;};
	virtual bool			Set(mcmcMatrix<int> &mask_label, irmm_Rect &bound1, MCMC_Particle &particle, mcmcMatrix<int> *pmx_taken1);
	virtual bool			Set(LinkList<PMCMC_PixelSet> &list_domain, MCMC_Particle &particle, mcmcMatrix<int> *pmx_taken1);

	virtual mcmcVector<float>	ComputeVote(const int nlable);
	virtual mcmcVector<double>	DiffuseTo(MCMC_Particle &particle, mcmcVector<double> &mx_mean, const int ipar);
	virtual double			Partition4Gaussian(const double mean, const double var);
	inline double			RobustCryingVoice(const double dis);
	virtual int			TotalCodingBits(void){return 0;};
	inline	bool			ConsiderThisPixel(const int row, const int col);

	virtual bool			Mean(const int nlabel);
	virtual bool			Variance(const int nlabel);
	virtual bool			LogLikelihood(const int nlabel);

	virtual irmm_Rect		GetBoundFromDomainList(void);

protected:
	virtual void		RobustVariance(mcmcMatrix<double> &mx_var);
	virtual void		RobustVariance(double &dvar);
	virtual double		RobustLoglik(const double dvalue);
	virtual void		GetXYDirections(mcmcVector<double> &vc_X, mcmcVector<double> &vc_Y, mcmcVector<double> &vc_N);

	virtual bool		MeanFromLabel(const int nlabel){return false;};
	virtual bool		MeanFromPixelSet(void){return false;};

	virtual bool		VarianceFromLabel(const int nlabel){return false;};
	virtual bool		VarianceFromPixelSet(void){return false;};
	
	virtual bool		LogLikelihoodFromLabel(const int nlabel){return false;};
	virtual bool		LogLikelihoodFromPixelSet(void){return false;};

protected:
	mcmcMatrix<int>		*pmx_label;		// label map for regions
	mcmcMatrix<int>		*pmx_taken;		// pixels taken by objects of other layers
	irmm_Rect		bound;
	MCMC_Particle	*pparticle;

	LinkList<PMCMC_PixelSet>	*plist_domain;
};

inline double MCMC_RegionModel::RobustCryingVoice(const double dist1)
{
	double dist=dist1;

	if (dist < CV_LOW)		dist = CV_LOW;
	else if (dist > CV_HIGH)	dist = CV_HIGH;

	return dist;
}

inline	bool MCMC_RegionModel::ConsiderThisPixel(const int row, const int col)
{
	if (pmx_taken==NULL || pmx_taken->Data(row,col)==0)
		return true;
	else
		return false;
}


/////////////////////////////////////////
// Pseudo Likelihood color texture model
class MCMC_Model_Texture : public MCMC_RegionModel
{
public:
	// construction & destruction
	MCMC_Model_Texture();
	virtual ~MCMC_Model_Texture();
	virtual void Free(void);

	// operators
	MCMC_Model_Texture& operator=(const MCMC_Model_Texture &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	virtual bool	Mean(const int nlabel);
	virtual bool	Variance(const int nlabel){return true;};
	virtual bool	LogLikelihood(const int nlabel);

	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual void	OutputInfo(char *info);
	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_value);

	virtual	void	DiffuseComputedMean(const int nlabel);
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void){;};
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);

	virtual mcmcVector<double> GetAMean(void){return vc_mean;};


public:
	mcmcVector<double>	vc_mean;			// this mean is useless in the most cases since texture model is fixed

protected:
	int				ktexture;
};


////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//        Models for regions in grey level images


/////////////////////////////////////////
// intensity model
class MCMC_Intensity_Gaussian : public MCMC_RegionModel
{
public:
	// constructions & destructions
	MCMC_Intensity_Gaussian();
	virtual ~MCMC_Intensity_Gaussian();
	virtual void Free(void);

	// operators
	MCMC_Intensity_Gaussian& operator=(const MCMC_Intensity_Gaussian &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	// robust statistics
	virtual void	UpdateLogLikelihood(const int nlabel, MCMC_PixelSet &list_pixels_old, MCMC_PixelSet &list_pixels_new);

	virtual	void	DiffuseComputedMean(const int nlabel);

	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_rgb);
	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);
	virtual void	OutputInfo(char *info);

	virtual mcmcVector<double> GetAMean(void);
	virtual int	TotalCodingBits(void);

protected:
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);

	virtual bool	VarianceFromLabel(const int nlabel);
	virtual bool	VarianceFromPixelSet(void);
	
	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);

public:
	double			intensity_mean;
	double			intensity_var;
	Histogram		bin_energy;

	RF_gaussian		rf_i;
};

///////////////////////////////////////////////
// pmf model directly
class MCMC_Intensity_Delta : public MCMC_RegionModel
{
public:
	// construction & destruction
	MCMC_Intensity_Delta();
	virtual ~MCMC_Intensity_Delta();
	virtual void Free(void);

	// operators
	MCMC_Intensity_Delta& operator=(const MCMC_Intensity_Delta &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	virtual bool	Variance(const int nlabel){return true;};
	virtual void	UpdateLogLikelihood(const int nlabel, MCMC_PixelSet &list_pixels_old, MCMC_PixelSet &list_pixels_new);

	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual void	OutputInfo(char *info);
	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_value);

	virtual	void	DiffuseComputedMean(const int nlabel){;};
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);

	virtual mcmcVector<double> GetAMean(void){mcmcVector<double> vc(1); vc(0)=intensity_mean; return vc;};
	virtual int	TotalCodingBits(void);

protected:
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);
	
	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);
	
public:
	double			intensity_mean;			// this mean is useless in the most cases since texture model is fixed
	Histogram		bin_energy;

protected:
	RF				rf_i;
};


////////////////////////////////////////////////////////////////////
class MCMC_Intensity_Surface : public MCMC_RegionModel
{
public:
	// construction & destruction
	MCMC_Intensity_Surface();
	~MCMC_Intensity_Surface();
	virtual void Free(void);

	// operators
	MCMC_Intensity_Surface& operator=(const MCMC_Intensity_Surface &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	virtual void	UpdateLogLikelihood(const int nlabel, MCMC_PixelSet &list_pixels_old, MCMC_PixelSet &list_pixels_new);

	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual void	OutputInfo(char *info);
	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_value);

	virtual	void	DiffuseComputedMean(const int nlabel){;};
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);

	virtual mcmcVector<double> GetAMean(void){mcmcVector<double> vc(1); vc(0)=intensity_mean; return vc;};
	virtual int	TotalCodingBits(void);

protected:
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);

	virtual bool	VarianceFromLabel(const int nlabel);
	virtual bool	VarianceFromPixelSet(void);

	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);
	
public:
	double				intensity_mean;			// this mean is useless in the most cases since texture model is fixed
	double				intensity_var;
	Histogram			bin_energy;
	MCMC_ControlPoints	surface;

protected:
	RF_gaussian			rf_i;
};


////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
//        Models for regions in color images



//////////////////////////////////
// in L*,u*,v*

// a region is interpreted as a single Gaussian
class MCMC_LuvColor_Gaussian : public MCMC_RegionModel
{
public:
	// constructions & destructions
	MCMC_LuvColor_Gaussian();
	~MCMC_LuvColor_Gaussian();
	virtual void Free(void);

	// operators
	MCMC_LuvColor_Gaussian& operator=(const MCMC_LuvColor_Gaussian &x);
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	// robust statistics
	
	virtual	void	DiffuseComputedMean(const int nlabel);

	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_luv);
	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);
	virtual void	OutputInfo(char *info);

	virtual mcmcVector<double> GetAMean(void);
	virtual int	TotalCodingBits(void);

protected:	
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);

	virtual bool	VarianceFromLabel(const int nlabel);
	virtual bool	VarianceFromPixelSet(void);

	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);

	virtual double  RobustLoglik(const double dvalue);

public:
	mcmcVector<double>	vc_mean;
	mcmcMatrix<double>	mx_variance;
	mcmcMatrix<double>	mx_variance_inv;

	double			d_std;

private:
	RF_gaussian		rf_l,rf_u,rf_v;
	mcmcMatrix<double>	mx_eigehvectors;
	
};


// a region is interpreted as a mixture of Gaussians
class MCMC_LuvColor_MixtureGaussians : public MCMC_RegionModel
{
public:
	// constructions & destructions
	MCMC_LuvColor_MixtureGaussians();
	~MCMC_LuvColor_MixtureGaussians();

	// operators
	MCMC_LuvColor_MixtureGaussians& operator=(const MCMC_LuvColor_MixtureGaussians &x);
	virtual void Free(void);
	
	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	// robust statistics

	virtual	void	DiffuseComputedMean(const int nlabel);

	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_luv);
	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);
	virtual void	OutputInfo(char *info);

	virtual mcmcVector<double> GetAMean(void);
	virtual int	TotalCodingBits(void);

protected:	
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);

	virtual bool	VarianceFromLabel(const int nlabel);
	virtual bool	VarianceFromPixelSet(void);

	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);

	virtual double  RobustLoglik(const double dvalue);

private:
	virtual int		CloserMode(const int j, const int i, mcmcVector<double> &vc_m1, mcmcVector<double> &vc_m2);
	virtual int		CloserMode(mcmcVector<double> &vc_pixel);

public:
	mcmcVector<double>	vc_means[2];			// two means of the modes
	mcmcMatrix<double>	mx_variances[2];
	double			alphs[2];
	mcmcMatrix<double>	mx_variance_invs[2];
	double			stds[2];	

private:
	RF_gaussian		rf_l[2],rf_u[2],rf_v[2];
	mcmcMatrix<double>	mx_eigehvectors[2];
	RF_uniform		rf_mode;
	
};

////////////////////////////////////////////////////////////////////
// surface model for color regions in L,u,v
//       L is considered as a separate variable from (u,v)
class MCMC_LuvColor_Surface : public MCMC_RegionModel
{
public:
	// construction & destruction
	MCMC_LuvColor_Surface();
	~MCMC_LuvColor_Surface();
	virtual void Free(void);

	// operators
	MCMC_LuvColor_Surface& operator=(const MCMC_LuvColor_Surface &x);
	

	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	// robust statistics

	virtual	void	DiffuseComputedMean(const int nlabel);

	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_luv);
	virtual double	GetLogPostProb(const int row, const int col, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual double	GetPdf(void);

	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);
	virtual void	OutputInfo(char *info);

	virtual mcmcVector<double> GetAMean(void){ return luv_mean; };
	//virtual int	TotalCodingBits(void){};

protected:	
	virtual bool	MeanFromLabel(const int nlabel);
	virtual bool	MeanFromPixelSet(void);

	virtual bool	VarianceFromLabel(const int nlabel);
	virtual bool	VarianceFromPixelSet(void);

	virtual bool	LogLikelihoodFromLabel(const int nlabel);
	virtual bool	LogLikelihoodFromPixelSet(void);

	virtual double  RobustLoglik(const double dvalue);


public:
	mcmcVector<double>		luv_mean;
	mcmcMatrix<double>		luv_var,luv_var_inv;
	MCMC_ControlPoints	l_surface,u_surface,v_surface;
	double				d_std;

private:
	RF_gaussian			rf_l,rf_u,rf_v;
	mcmcMatrix<double>		mx_eigehvectors;
};


#endif